package server

import (
	"ginfwk/framework/core/gins"
	"ginfwk/framework/core/gins/gengine"
	"ginfwk/framework/kernel"
	"ginfwk/infrastructure/component/config"
	"ginfwk/infrastructure/component/logger"
	di "github.com/samber/do"
)

type HttpServer struct {
	addr    string
	gEngine *gengine.GEngine

	httpKernel kernel.HttpKernel
}

// NewHttpServer
// 从配置文件中读取的监听地址
func NewHttpServer(httpKernel kernel.HttpKernel) *HttpServer {
	server := &HttpServer{
		httpKernel: httpKernel,
	}
	// 指定engine的context使用的application
	server.gEngine = gengine.New()

	// 初始化
	server.Init()
	return server
}

// Init 注册配置
func (s *HttpServer) Init() {
	// s.gEngine.HandleMethodNotAllowed = true

	// 启动配置
	s.Bootstrap()

	// 注册服务提供者
	s.RegisterProviders()

	// 服务初始化
	s.ServerInit()
}

func (s *HttpServer) ServerInit() {
	// 注入自定义路由打印
	ginRoutePrintRegister, err := di.Invoke[gins.GinRoutePrintRegister](nil)
	if err != nil || ginRoutePrintRegister == nil {
		logger.Warnf("found no gin route printer, %s", err)
	} else {
		ginRoutePrintRegister(s.gEngine)
	}

	// 注册路由
	s.RegisterRouters()

	// 注册配置
	s.addr = config.Global().Server.Addr
}

// Bootstrap 启动配置
func (s *HttpServer) Bootstrap() {
	bootstrapperList := s.httpKernel.BootStrappers()
	for _, bootstrapper := range bootstrapperList {
		bootstrapper()
	}
}

// RegisterProviders 注册服务提供者
func (s *HttpServer) RegisterProviders() {
	providerList := s.httpKernel.Providers()
	for _, providerRegister := range providerList {
		providerRegister()
	}
}

// RegisterRouters 注册路由配置
func (s *HttpServer) RegisterRouters() {
	r := s.getBaseRouter()

	register, err := di.Invoke[gins.RouterRegister](nil)
	if err != nil {
		logger.Fatalf("failed to find http router: %s", err)
	}

	register.Register(r)
}

func (s *HttpServer) getBaseRouter() *gengine.GEngine {
	r := s.gEngine

	// 注册默认的中间件
	httpMiddlewares := s.httpKernel.Middlewares()
	if len(httpMiddlewares) > 0 {
		r.Use(httpMiddlewares...)
	}

	// 注册无路由handler,使没有路由匹配时,也能使中间件生效(CORS)
	s.gEngine.NoRoute()
	return r
}

func (s *HttpServer) GetEngine() *gengine.GEngine {
	return s.gEngine
}

// Run 启动服务
func (s *HttpServer) Run() {
	if err := s.gEngine.Run(s.addr); err != nil {
		logger.Fatalf("failed to start http server: %s", err)
	}
	logger.Infof("stopped server succeed.")
}
